import { Router } from 'vue-router'
import { useUserStore } from '../../store/user'
import { usePermissionStore } from '../../store/permission'
import { isMicroAppPath } from '../../utils/microAppHelper'
import { ElMessage } from 'element-plus'
import { useUserProfile } from '../../composables/useUserProfile'
import { ROLE_CODES } from '../../store/role'
import { microApps } from '../../microApps.config'

// 白名单路由，无需登录即可访问
const WHITE_LIST = ['/login', '/404', '/403']

// 缓存已验证的路径
const validatedPaths = new Set<string>()
const invalidPaths = new Set<string>()

export function createPermissionGuard(router: Router) {
  router.beforeEach(async (to, from, next) => {
    const userStore = useUserStore()
    const permissionStore = usePermissionStore()
    const token = userStore.getToken
    
    // 1. 快速路径处理
    if (!token) return WHITE_LIST.includes(to.path) ? next() : next({ path: '/login', query: { redirect: to.path } })
    if (to.path === '/login') return next({ path: '/' })
    if (WHITE_LIST.includes(to.path)) return next()
    
    // 获取用户角色
    const userRoles = userStore.getUserInfo.roles || []
    
    // 超级管理员直接放行
    if (userRoles.includes(ROLE_CODES.SUPER_ADMIN)) return next()
    
    // 2. 微应用路径特殊处理 - 只检查角色权限
    if (isMicroAppPath(to.path)) {
      const appPath = to.path.split('/')[1]
      const microApp = microApps.find(app => app.activeRule.includes(`/${appPath}`))
      
      console.log('[PermissionGuard] 微应用权限检查:', {
        path: to.path,
        appPath,
        microApp: microApp?.name,
        requiredRoles: microApp?.requiredRoles,
        userRoles,
        hasRole: !microApp?.requiredRoles?.length || microApp.requiredRoles.some(role => userRoles.includes(role))
      })
      
      // 检查角色权限
      const requiredRoles = microApp?.requiredRoles || []
      const hasRole = !requiredRoles.length || requiredRoles.some(role => userRoles.includes(role))
      
      if (!hasRole) {
        console.log('[PermissionGuard] 权限不足，拒绝访问微应用:', to.path)
        ElMessage.error('您没有访问此应用的权限')
        return next({ name: '403', query: { path: to.fullPath } })
      }
      
      console.log('[PermissionGuard] 微应用权限检查通过:', to.path)
      return next()
    }
    
    // 3. 加载用户信息和权限（如果尚未加载）
    if (!userStore.getUserInfo.userId || !permissionStore.permissions.length) {
      try {
        await useUserProfile().fetchUserProfile()
        
        // 动态添加路由
        const accessRoutes = permissionStore.getAccessRoutes
        const routesAdded = accessRoutes.some(route => !router.hasRoute(route.name as string) && router.addRoute(route))
        
        if (routesAdded && to.path !== from.path) return next({ ...to, replace: true })
      } catch (error) {
        console.error('权限初始化失败:', error)
        console.warn('权限加载失败，但允许继续访问基本功能')
      }
    }
    
    // 4. 检查路由是否存在
    if (!router.hasRoute(to.name as string)) {
      if (validatedPaths.has(to.path)) return next({ name: '403', query: { path: to.fullPath } })
      if (invalidPaths.has(to.path)) return next({ name: '404', query: { path: to.fullPath } })
      
      const isValidPath = ['/', '/about', '/dashboard', '/profile'].includes(to.path)
      validatedPaths.add(to.path)
      return next({ name: isValidPath ? '403' : '404', query: { path: to.fullPath } })
    }
    
    // 5. 检查路由权限
    const routeMeta = to.meta || {}
    const requiredRoles = routeMeta.requiredRoles as string[] || []
    const permission = routeMeta.permission as string
    
    // 检查角色权限
    const hasRole = !requiredRoles.length || requiredRoles.some(role => userRoles.includes(role))
    if (!hasRole) {
      ElMessage.error('您没有访问此页面的权限')
      return next({ name: '403', query: { path: to.fullPath } })
    }
    
    // 检查权限码
    if (permission && !permissionStore.hasPermission(permission)) {
      ElMessage.error('您没有访问此页面的权限')
      return next({ name: '403', query: { path: to.fullPath } })
    }
    
    // 6. 加载按钮权限
    const menuId = routeMeta.menuId
    if (menuId && !permissionStore.loadedMenuIds.has(menuId as string | number)) {
      permissionStore.loadButtonPermissions(menuId as string | number, to.path)
    }
    
    return next()
  })
} 